package com.hanthink.common.utils.mdeia;

import java.io.File;
import java.io.FileInputStream;
import java.io.InputStream;
import java.util.HashMap;
import java.util.Map;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.web.multipart.MultipartFile;

import com.hanthink.common.config.hanthinkConfig;
import com.hanthink.common.utils.ProcessUtil;
import com.hanthink.common.utils.file.FileUploadUtils;
import com.hanthink.common.utils.file.FileUtils;


/**
* <p>Title: MediaWapper</p>  
* <p>Description: video处理- 对外暴露的接口，所有音频相关的操作都通过它来执行</p>  
* @author vondser
* @date 2020年12月25日
 */
public class MediaWapper {
	
	protected final static Logger log = LoggerFactory.getLogger(MediaWapper.class);

    /**
     * <p>Title: of</p>  
     * <p>Description: InputStream （文件输入流）</p>  
     * @param inputStream
     * @return
     */
    public static Builder<InputStream> of(InputStream inputStream) {
        Builder<InputStream> builder = new Builder<>();
        return builder.setSource(inputStream);
    }
    
    /**
     * <p>Title: of</p>  
     * <p>Description: MultipartFile 文件</p>  
     * @param MultipartFile
     * @return
     */
    public static Builder<MultipartFile> of(MultipartFile file) {
        Builder<MultipartFile> builder = new Builder<>();
        return builder.setSource(file);
    }


    private static void checkNotNull(Object obj, String msg) {
        if (obj == null) {
            throw new IllegalStateException(msg);
        }
    }

    private static boolean run(String cmd) {
        try {
            return ProcessUtil.instance().process(cmd);
        } catch (Exception e) {
            log.error("operate audio error! cmd: {}, e: {}", cmd, e);
            return false;
        }
    }


    public static class Builder<T> {
        /**
         * 输入源
         */
        private T source;

        /**
         * 输出音频格式
         */
        private String outputType;


        /**
         * 命令行参数
         */
        private final Map<String, Object> options = new HashMap<>();


        /**
         * 临时文件信息
         */
        private String tempFileInfo;
        
        private String tempOutputFile;


        public Builder<T> setSource(T source) {
            this.source = source;
            return this;
        }

        public Builder<T> setOutputType(String outputType) {
            this.outputType = outputType;
            return this;
        }

        public Builder<T> addOption(String conf, Object val) {
            this.options.put(conf, val);
            return this;
        }


        private String builder() throws Exception {

            checkNotNull(source, "src file should not be null!");

            checkNotNull(outputType, "output Audio type should not be null!");


            tempFileInfo = FileUploadUtils.upload(hanthinkConfig.getAvatarPath(), (MultipartFile) source);
            
            tempOutputFile = tempFileInfo + "." +outputType;

            return new MediaOptions().setSrc(MediaOptions.TMP_MEDIA_DEFAULT_DISK + tempFileInfo)
                    .setDest(MediaOptions.TMP_MEDIA_DEFAULT_DISK + tempOutputFile)
                    .addOption("y", "") // 覆盖写
                    .addOption("b:v", "1M")                         
                    .addOption("vf", "scale=854:480")                          
                    .addOption("b:a", "32k")                         
                    .addOption("vol", "200")                         
                    .addOption("vcodec", "libx264")                      
                    .addOption("threads", "5")                     
                    .addOption("preset", "veryfast")                      
                    .addOption("strict", "-2")                      
                    .build();
        }


        public InputStream asStream() throws Exception {
            String output = asFile();

            if (output == null) {
                return null;
            }


            return new FileInputStream(new File(output));
        }


        public String asFile() throws Exception {
            String cmd = builder();
            if(run(cmd)) {
            	boolean deleteFile = FileUtils.deleteFile(MediaOptions.TMP_MEDIA_DEFAULT_DISK + tempFileInfo);
            	if(deleteFile) {
            		return MediaOptions.TMP_MEDIA_DEFAULT_DISK + tempOutputFile;
            	}
            }
            return null;
        }
    }
}
